package com.bj58.groupbuy.action.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import com.bj58.groupbuy.action.model.IESend;


public class EmailReportUtil {
	
	private SomePublicUtil  spu = new SomePublicUtil();
	private static VelocityTools vt = new VelocityTools();
	private ReflectUtil reflectUtil = new ReflectUtil();
	
	
	/**将今、昨、上周 三天数据按照VO的指标列合并数据，计算环比、同比等数据。
	 * 最后以 指标、今日数据、昨日数据、环比、上周、同比的形式（字符）返回
	 * @param <T>
	 * @param tempList   数据集
	 * @param clazz	
	 * @param speEname	百分比指标名集合
	 * @param dateMap		日期MAP   放入三天的日期   key分别为nowDate、lastDate、lastWeek
	 * @param dateKeyName	 此VO的日期项名
	 * @param dicsList 需要展示及计算的字段字典 根据需要从从注解中获取(spu.getECDicByAnnotation)
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public <T>List<String>  conformDataTypeOne (List<T> tempList,Class<T> clazz,List<String> speEname,Map<String,String>  dateMap,String dateKeyName ,List<String> dicsList) throws Exception{
		
		String nowDate = dateMap.get("nowDate");
		String lastDate = dateMap.get("lastDate");
		String lastWeek = dateMap.get("lastWeek");
		
		Map<String,T> tempMap = new HashMap<String, T>();
		for(T vo : tempList){
			String statDate = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(dateKeyName)).invoke(vo).toString();  //获取日期
			tempMap.put(statDate, vo);
		}
		
//		List<String>  dicsList = spu.getECDicByAnnotation(clazz);
		List<String>  showValuesList = new ArrayList<String>();
		
		for(String dic : dicsList){
			String cname = dic.split(",")[1];
			String ename = dic.split(",")[0];
			//该指标的数据类型
			Field field = clazz.getDeclaredField(ename);
			Class<?> filedCls = field.getType();
			int  colType = 0; //数据类型  0 : 整型  1：浮点  2：百分比
			if(filedCls == int.class || filedCls == Integer.class || filedCls == long.class || filedCls == Long.class) {
				colType = 0 ; 
			}else if(filedCls == double.class || filedCls == Double.class) {
				if(null != speEname && speEname.contains(ename)){ //此集合中的指标为特殊类，为百分比数值
					colType = 2 ; 
				}else{
					colType = 1 ; 
				}
			} 
			
			StringBuffer  showValues = new StringBuffer(); 
			//指标名
			showValues.append(cname+";");
			
			//今日数据
			Object nowData = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(ename)).invoke(tempMap.get(nowDate));
			showValues.append(vt.tranValueByType(nowData, colType)+";");
			
			//昨日数据
			Object yesterData = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(ename)).invoke(tempMap.get(lastDate));
			showValues.append(vt.tranValueByType(yesterData, colType)+";");
			
			//日环比
			if(null != nowData && null != yesterData){
				showValues.append(vt.compRate(nowData, yesterData)+";");
			}else{
				showValues.append("--"+";");
			}
			
			//上周数据
			Object lastWeekData = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(ename)).invoke(tempMap.get(lastWeek));
			showValues.append(vt.tranValueByType(lastWeekData, colType)+";");
			
			//周同比
			if(null != nowData && null != lastWeekData){
				showValues.append(vt.compRate(nowData, lastWeekData)+";");
			}else{
				showValues.append("--"+";");
			}
			
			showValuesList.add(showValues.toString());
		}
		
		return showValuesList;
	}
	
	
	/** 组合数据  X轴为 城市OR类别 +指标     Y轴为日期
	 *  vo Column  命名规则  
	 *  分组KEY的属性名=key；日期属性名=date；展示属性名=show；百分比属性名=cent；展示值属性名=value
	 *  一个属性可多重名  中间以&隔开
	 * @param <T>
	 * @param tempList   数据集  
	 * @param beginDate 开始日期
	 * @param endDate 结束日期
	 * @param clazz  
	 * @param citys  城市OR类别集合
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public <T> List<T> conformDataTypeTwo (List<T> tempList ,String beginDate,String endDate,Class<T> clazz,String[] citys) throws Exception{
		
		List<String> keyNames = new ArrayList<String>(); // 分组KEY的属性名    key
		String statDateEname = ""; // 日期属性名   date
		String showEname = ""; // 展示属性名  show
		List<String> centList = new ArrayList<String>(); // 百分比属性名 cent
		List<String> showValuesList = new ArrayList<String>(); // 展示值属性名 value
		
		List<String> dicList = spu.getECDicByAnnotation(clazz);
		for(String dic : dicList) {
			String ename = dic.split(",")[0];
			String cname = dic.split(",")[1];
			if(cname.contains("key")){
				keyNames.add(ename);
			}
			if(cname.contains("date")){
				statDateEname = ename;
			}
			if(cname.contains("show")){
				showEname = ename;
			}
			if(cname.contains("value")){
				showValuesList.add(ename);
			}
			if(cname.contains("cent")){
				centList.add(ename);
			}
		}
		
		HashMap<String,T>  tempMap = new HashMap<String, T>();
		for(T vo : tempList){
			StringBuffer key = new StringBuffer();
			for(int i = 0 ; i < keyNames.size(); i++){
				String keyName = keyNames.get(i);
				String keyValue = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(keyName)).invoke(vo).toString();  
				key.append(keyValue);
				if((i+1) < keyNames.size() ){
					key.append(",");
				}
			}
			tempMap.put(key.toString(), vo);
		}
		
		List<T> finalList = new ArrayList<T>();
		String nowComDate = beginDate;
		while(true){
			T vo = clazz.newInstance();
			List<String>  values = new ArrayList<String>();
		
			//设置日期
			reflectUtil.getSetterMethod(clazz, clazz.getDeclaredField(statDateEname)).invoke(vo, new Object[] { nowComDate }); 

			for(String city : citys){
				String key = nowComDate+","+city;
				if(tempMap.containsKey(key)){
					for(String showValue : showValuesList){
						//该指标的数据类型
						Field field = clazz.getDeclaredField(showValue);
						Class<?> filedCls = field.getType();
						int  colType = 0; //数据类型  0 : 整型  1：浮点  2：百分比
						if(filedCls == int.class || filedCls == Integer.class || filedCls == long.class || filedCls == Long.class) {
							colType = 0 ; 
						}else if(filedCls == double.class || filedCls == Double.class) {
							if(centList.contains(showValue)){ //此集合中的指标为特殊类，为百分比数值
								colType = 2 ; 
							}else{
								colType = 1 ; 
							}
						} 
						Object tempValue = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(showValue)).invoke(tempMap.get(key));
//						System.out.println(key+","+showValue+":"+tempValue);
						values.add(vt.tranValueByType(tempValue, colType));
					}
				}else{
					for(int i = 0 ; i < showValuesList.size() ; i++){
						values.add("--");
					}
				}
			}
			//SET展示值 String类型
			reflectUtil.getSetterMethod(clazz, clazz.getDeclaredField(showEname)).invoke(vo, new Object[] { values.toArray(new String[values.size()]) });
			finalList.add(vo);
			if(nowComDate.equals(endDate)){
				break;
			}
			nowComDate = DateUtil.getStringDate(DateUtil.getDateAfter(DateUtil.strToDate(nowComDate, "yyyy-MM-dd"), 1), "yyyy-MM-dd");
		}
		return finalList;
	}
	
	
	/**组合数据  X轴为类别（一级) +指标（二级）     Y轴为城市
	 * @param <T>
	 * @param tempList
	 * @param clazz
	 * @param citys
	 * @param cates
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public <T> List<T> conformDataTypeThree (List<T> tempList,Class<T> clazz,String[] citys,String[] cates) throws Exception{
		
		List<String> keyNames = new ArrayList<String>(); // 分组KEY的属性名    key
		String cityEname = ""; // 城市属性名   city
		String showEname = ""; // 展示属性名  show
		List<String> centList = new ArrayList<String>(); // 百分比属性名 cent
		List<String> showValuesList = new ArrayList<String>(); // 展示值属性名 value
		
		List<String> dicList = spu.getECDicByAnnotation(clazz);
		for(String dic : dicList) {
			String ename = dic.split(",")[0];
			String cname = dic.split(",")[1];
			if(cname.contains("key")){
				keyNames.add(ename);
			}
			if(cname.contains("city")){
				cityEname = ename;
			}
			if(cname.contains("show")){
				showEname = ename;
			}
			if(cname.contains("value")){
				showValuesList.add(ename);
			}
			if(cname.contains("cent")){
				centList.add(ename);
			}
		}
		
		HashMap<String,T>  tempMap = new HashMap<String, T>();
		for(T vo : tempList){
			StringBuffer key = new StringBuffer();
			for(int i = 0 ; i < keyNames.size(); i++){
				String keyName = keyNames.get(i);
				String keyValue = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(keyName)).invoke(vo).toString();  
				key.append(keyValue);
				if((i+1) < keyNames.size() ){
					key.append(",");
				}
			}
			tempMap.put(key.toString(), vo);
		}
		
		List<T> finalList = new ArrayList<T>();
		
		for(String city : citys){
			T vo = clazz.newInstance();
			List<String>  values = new ArrayList<String>();
			//设置城市
			reflectUtil.getSetterMethod(clazz, clazz.getDeclaredField(cityEname)).invoke(vo, new Object[] { city }); 

			for(String cate : cates){
				String key = city+","+cate;
				if(tempMap.containsKey(key)){
					for(String showValue : showValuesList){
						//该指标的数据类型
						Field field = clazz.getDeclaredField(showValue);
						Class<?> filedCls = field.getType();
						int  colType = 0; //数据类型  0 : 整型  1：浮点  2：百分比
						if(filedCls == int.class || filedCls == Integer.class || filedCls == long.class || filedCls == Long.class) {
							colType = 0 ; 
						}else if(filedCls == double.class || filedCls == Double.class) {
							if(centList.contains(showValue)){ //此集合中的指标为特殊类，为百分比数值
								colType = 2 ; 
							}else{
								colType = 1 ; 
							}
						} 
						Object tempValue = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(showValue)).invoke(tempMap.get(key));
						values.add(vt.tranValueByType(tempValue, colType));
					}
				}else{
					for(int i = 0 ; i < showValuesList.size() ; i++){
						values.add("--");
					}
				}
			}
			//SET展示值 String类型
			reflectUtil.getSetterMethod(clazz, clazz.getDeclaredField(showEname)).invoke(vo, new Object[] { values.toArray(new String[values.size()]) });
			finalList.add(vo);
		}
		return finalList;
	}
	
	
	/**根据基础各日期的数据     以查询指标为维度   将显示指标的同比、环比计算出，并将每行数据以显示的顺序拼为字符串返回
	 * @param <T>
	 * @param tempList     数据集
	 * @param clazz	
	 * @param gbCol	        维度指标
	 * @param showCols	显示指标
	 * @param dateCols		日期字段名
	 * @param percentList	百分比指标
	 * @param dateList	    日期集合  依次是 当日、昨日、上周 的日期
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("static-access")
	public  <T>List<String> conformDataTypeFour (List<T> tempList,Class<T> clazz,String gbCol, List<String> showCols,String dateCol,List<String> percentList,List<String> dateList) throws Exception{
		
		//第一层K为 gbCols 即维度指标    第二层K为日期
		TreeMap<String,Map<String,T>> dataMap = new TreeMap<String, Map<String,T>>();
		
		for(T vo : tempList){
			String gbKey  = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(gbCol)).invoke(vo).toString();
			Map<String,T> tmap = new HashMap<String, T>();
			if(dataMap.containsKey(gbKey)){
				tmap = dataMap.get(gbKey);
			}
			
			String dateKey  = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(dateCol)).invoke(vo).toString();
			tmap.put(dateKey, vo);
			dataMap.put(gbKey, tmap);
		}
		
		
		List<String>  finalList = new ArrayList<String>();
		for(Iterator<String> it = dataMap.keySet().iterator(); it.hasNext();){
			String gbKey = it.next(); //维度名
			Map<String,T> tmap = dataMap.get(gbKey);
			
			StringBuffer values = new StringBuffer();
			values.append(gbKey+";");
			
			for(String showCol : showCols){
				//字段数据类型
				Field field = clazz.getDeclaredField(showCol);
				Class<?> filedCls = field.getType();
				int  colType = 0; //数据类型  0 : 整型  1：浮点  2：百分比
				if(filedCls == int.class || filedCls == Integer.class || filedCls == long.class || filedCls == Long.class) {
					colType = 0 ; 
				}else if(filedCls == double.class || filedCls == Double.class) {
					if(null !=percentList &&  percentList.contains(showCol)){
						colType = 2 ; 
					}else{
						colType = 1 ; 
					}
				} 
				
				//今日数据
				if(!tmap.containsKey(dateList.get(0))){
					continue;
				}
				Object nowData = reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(showCol)).invoke(tmap.get(dateList.get(0)));
			
				if(null != nowData){
					values.append(vt.tranValueByType(nowData, colType)+";");
				}else{
					values.append("--"+";");
				}
				//昨日数据
				if(tmap.containsKey(dateList.get(1))){
					Object yesterData =  reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(showCol)).invoke(tmap.get(dateList.get(1)));
					//环比
					if(null != nowData && null != yesterData){
						values.append(vt.compRate2(nowData, yesterData)+";");
					}else{
						values.append("--"+";");
					}
				}else{
					values.append("--"+";");
				}
				
				if(tmap.containsKey(dateList.get(2))){
					//上周数据
					Object lastWeekData =  reflectUtil.getGetterMethod(clazz, clazz.getDeclaredField(showCol)).invoke(tmap.get(dateList.get(2)));
					//同比
					if(null != nowData && null != lastWeekData){
						values.append(vt.compRate2(nowData, lastWeekData)+";");
					}else{
						values.append("--"+";");
					}
				}else{
					values.append("--"+";");
				}
				
			}
			if(values.toString().split(";").length > 1){
				finalList.add(values.toString());
			}
			
		}
		
		return finalList;
	}
	
	
	
	/**自定义邮件 模板1 同比、环比解析
	 * @param tempDataMap    key = 行表头;日期  ； value = 指标：值
	 * @param dateList	 日期集   先后为 今、昨、上周
	 * @return    key = 行表头    value = 指标：今日值;同比;环比
	 * @throws Exception
	 */
	public Map<String,Map<String,String>>  conformDataForIETypeOne(IESend ieSend,Map<String,Map<String,Object>> tempDataMap, Map<String,String> speIndexType,List<String> dateList) throws Exception{
		
		Set<String> keySet = tempDataMap.keySet();
		Set<String> rowKeySet = new HashSet<String>();
		for (String key : keySet) {
			rowKeySet.add(key.split(";")[0]);
		}
	
		
		Map<String,Map<String,String>> dealMap = new HashMap<String, Map<String,String>>();//key = 行表头    value = 指标：今日值;同比;环比
		
		for (String rowKey : rowKeySet) {
			
			String today = dateList.get(0);
			String yesterday = dateList.get(1);
			String lastWeek	 = dateList.get(2);
			
			String todayKey = rowKey + ";" + today;
			String yesterdayKey = rowKey + ";" + yesterday;
			String lastWeekKey = rowKey + ";" + lastWeek;
				
			
			Map<String,Object> todayMap = tempDataMap.get(todayKey);
			if(todayMap==null)
				continue;
			
			Map<String,Object> yesterdayMap = new HashMap<String, Object>();
			if(tempDataMap.containsKey(yesterdayKey)){
				yesterdayMap = tempDataMap.get(yesterdayKey);
			}
			Map<String,Object> lastWeekMap = new HashMap<String, Object>();
			if(tempDataMap.containsKey(lastWeekKey)){
				lastWeekMap = tempDataMap.get(lastWeekKey);
			}
			
			Set<String> indexSet=new HashSet<String>();
			indexSet.addAll(todayMap.keySet());
			indexSet.addAll(yesterdayMap.keySet());
			indexSet.addAll(lastWeekMap.keySet());
			
			Map<String,String>  compMap = new HashMap<String, String>();
			for(Iterator<String> it = indexSet.iterator(); it.hasNext();){
				String index = it.next();
				String type=speIndexType.get(index); //数据类型  0 : 整型  1：浮点   如果是百分比要保留4位小数
				StringBuffer newValue = new StringBuffer();
				ieSend.setTdNum(ieSend.getTdNum()+2);
				//今日数据
				Object todayValue = todayMap.get(index);
//				System.out.println(rowKey+":"+index+":"+todayValue);
				if(todayValue==null || "--".equals(todayValue.toString())){
					ieSend.setAbnormalTd(ieSend.getAbnormalTd()+2);
					newValue.append("--;");
//					System.out.println(index+":--");
				}
				else{
//					System.out.println(todayValue+":"+index+"---"+colType);
					newValue.append(vt.tranValueByTypeForIE(todayValue, type)+";");
				}
				//昨日数据  - 昨日，日比
				Object yesterdayValue = yesterdayMap.get(index);
				if(!yesterdayMap.isEmpty() && yesterdayMap.size() > 0 && yesterdayMap.containsKey(index)){
					
					newValue.append(vt.tranValueByTypeForIE(yesterdayValue, type)+";");
					addAbnormalRate(ieSend,todayValue, yesterdayValue);
				}else{
					newValue.append("--;");
					ieSend.setAbnormalTd(ieSend.getAbnormalTd()+1);
				}
				newValue.append(vt.compRate2(todayValue, yesterdayValue)+";");
				//上周数据 - 周比
				Object lastWeekValue = lastWeekMap.get(index);
				if(!lastWeekMap.isEmpty() && lastWeekMap.size() > 0 && lastWeekMap.containsKey(index)){
					newValue.append(vt.tranValueByTypeForIE(lastWeekValue, type)+";");
					addAbnormalRate(ieSend,todayValue, lastWeekValue);
				}else{
					newValue.append("--;");
					ieSend.setAbnormalTd(ieSend.getAbnormalTd()+1);
				}
				newValue.append(vt.compRate2(todayValue, lastWeekValue)+";");
				compMap.put(index, newValue.toString());
			}
			dealMap.put(rowKey, compMap);
		}
		
		return dealMap;
	}
	
	
	
	/**自定义邮件 模板2 同比、环比解析
	 * @param tempDataMap    key = 行表头;日期  ； value = 指标：值
	 * @param dateList	 日期集   先后为 今、昨、上周
	 *  @param indexTypeMap	特殊计算指标:是否百分比类型
	 * @return    key = 行表头    value = 指标：今日值;同比;环比
	 * @throws Exception
	 */
	public Map<String,String>  conformDataForIETypeTwo(IESend ieSend,Map<String,Object> tempDataMap, List<String> dateList,HashMap<String,String> indexTypeMap) throws Exception{
		
		Set<String> keySet = tempDataMap.keySet();
		Set<String> rowKeySet = new HashSet<String>();
		for (String key : keySet) {
			rowKeySet.add(key.split(";")[0]);
		}
	
		
		Map<String,String> dealMap = new HashMap<String, String>(); //key = 行表头    value = 今日,昨日,日比,上周,周比
		
		for (String rowKey : rowKeySet) {
			String index=rowKey.split("#")[1];
			String today = dateList.get(0);
			String yesterday = dateList.get(1);
			String lastWeek	 = dateList.get(2);
			
			String todayKey = rowKey + ";" + today;
			String yesterdayKey = rowKey + ";" + yesterday;
			String lastWeekKey = rowKey + ";" + lastWeek;
				
			
			Object todayValue = tempDataMap.get(todayKey); //今日数据
			ieSend.setTdNum(ieSend.getTdNum()+2);
			
			Object yesterdayValue = "";//昨日数据
			if(tempDataMap.containsKey(yesterdayKey)){
				yesterdayValue = tempDataMap.get(yesterdayKey);
			}
			
			Object lastWeekValue = ""; //上周数据
			if(tempDataMap.containsKey(lastWeekKey)){
				lastWeekValue = tempDataMap.get(lastWeekKey);
			}
			
			
			//计算
			StringBuffer newValue = new StringBuffer();
			String colType=indexTypeMap.get(index); // 数据类型  0 : 整型  1：浮点    如果是百分比要保留4位小数
			//今日数据
			if(todayValue==null || "--".equals(todayValue.toString())){
				ieSend.setAbnormalTd(ieSend.getAbnormalTd()+2);
				newValue.append("--;");
			}
			else{
				String finalVal=vt.tranValueByTypeForIE(todayValue, colType);
				if("1".equals(colType)){	//百分比类型
					finalVal=vt.comRate(finalVal);
				}
				newValue.append(finalVal+";");
			}
//			int  colType = 0; //数据类型  0 : 整型  1：浮点   
//			if(String.valueOf(todayValue).contains(".")){
//				colType = 1;
//			}
//			String type=indexTypeMap.get(index);
//			if("1".equals(type)){
//				newValue.append(vt.comRate(String.valueOf(todayValue))+";");
//			}
//			else{
//				newValue.append(vt.tranValueByType(todayValue, colType)+";");
//			}
			//昨日数据 &  日比
			if(!"".equals(yesterdayValue.toString())){
				String finalVal=vt.tranValueByTypeForIE(yesterdayValue, colType);
				if("1".equals(colType)){
					newValue.append(vt.comRate(finalVal)+";");
				}
				else{
					newValue.append(finalVal+";");
				}
//				System.out.println(todayValue+"--"+yesterdayValue);
				addAbnormalRate(ieSend,todayValue, yesterdayValue);
			}else{
				newValue.append("--;");
				ieSend.setAbnormalTd(ieSend.getAbnormalTd()+2);
			}
			newValue.append(vt.compRate2(todayValue, yesterdayValue)+";");
			//上周数据  &  周比
			if(!"".equals(lastWeekValue.toString())){
				String finalVal=vt.tranValueByTypeForIE(lastWeekValue, colType);
				if("1".equals(colType)){
					newValue.append(vt.comRate(finalVal)+";");
				}
				else{
					newValue.append(finalVal+";");
				}
				addAbnormalRate(ieSend,todayValue, lastWeekValue);
			}else{
				newValue.append("--;");
				ieSend.setAbnormalTd(ieSend.getAbnormalTd()+2);
			}
			newValue.append(vt.compRate2(todayValue, lastWeekValue)+";");
			
			dealMap.put(rowKey, newValue.toString());
		}
		
		return dealMap;
	}
  
	public String  conformDataForIETypeThree(Object value,String type) throws Exception{
		
			String finalVal="";
			try{
				finalVal=vt.tranValueByTypeForIE(value, type);
			}catch(Exception e){
				e.printStackTrace();
				return "--";
			}
			return finalVal;
	}

	/**根据阈值检查同环比
	 * @param ieSend
	 * @param todayVal
	 * @param lastVal
	 */
	public static void addAbnormalRate(IESend ieSend,Object todayVal,Object lastVal){
		double rate=vt.compRate3(todayVal, lastVal);
		if(Math.abs(rate)>ieSend.getThreshold()){
			if(Math.abs(rate) > 1.5*ieSend.getThreshold() || Math.abs(rate) > 1)	//超过阈值的1.5倍或者超过100%
				ieSend.setAbnormalTd(ieSend.getAbnormalTd()+2); //不正常数据+2
			else
				ieSend.setAbnormalTd(ieSend.getAbnormalTd()+1);//不正常数据+1
		}
	}
}
